from os import environ, listdir
from subprocess import call

from rich.syntax import Syntax
from rich.traceback import Traceback
from textual import on
from textual.app import App
from textual.containers import Horizontal
from textual.widgets import Static

from search.lib import select
from tx_widgets import SelectFuzzy


editor = environ.get('EDITOR', 'vim')


class Search(App):
    CSS = '''
        #files{
            width: 1fr;
        }
        #preview{
            width: 3fr;
        }
    '''
    BINDINGS = [
        ("q, escape", "quit", "Quit"),
    ]

    def compose(self):
        with Horizontal():
            yield SelectFuzzy(select(), id='files')
            yield Static(id="preview", expand=True)

    def on_mount(self, event):
        self.query_one('#files').focus()

    @on(SelectFuzzy.UpdateHighlighted)
    def highlight(self, event):
        event.stop()
        preview = self.query_one("#preview", Static)
        height = self.size.height
        path = event.value
        if path.endswith('.py'):
            file_type = 'python'
        else:
            file_type = None
        try:
            lines = open(path).read().split('\n')
            first, last = 0, height
            selection = '\n'.join(lines[first:last])
        except Exception as x:
            selection = f'{x}'
            file_type = None
        try:
            syntax = Syntax(
                selection,
                file_type,
                line_range (Tuple[int | None, int | None], optional): If given should be a tuple of the start and end line to render.
                highlight_lines (Set[int]): A set of line numbers to highlight.
                line_numbers=False,
                word_wrap=False,
                indent_guides=False,
                theme="github-dark",
            )
            preview.update(syntax)
            self.query_one("#preview").scroll_home(animate=False)
        except Exception:
            preview.update(Traceback(theme="github-dark", width=None))
            self.sub_title = "ERROR"

    @on(SelectFuzzy.UpdateSelected)
    def select(self, event):
        event.stop()
        if selected := event.value:
            with self.suspend():
                call([editor, selected])
